//////////////////////////////////////////////////////////////////////////////////
//                                                                              //
//  This file is part of the buola project (https://code.google.com/p/buola/).  //
//                                                                              //
//  Copyright(c) 2007-2011 Xavi Gratal                                          //
//  gratal AT gmail DOT com                                                     //
//                                                                              //
//  Buola is free software: you can redistribute it and/or modify               //
//  it under the terms of the GNU General Public License as published by        //
//  the Free Software Foundation, either version 3 of the License, or           //
//  (at your option) any later version.                                         //
//                                                                              //
//  Buola is distributed in the hope that it will be useful,                    //
//  but WITHOUT ANY WARRANTY; without even the implied warranty of              //
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               //
//  GNU General Public License for more details.                                //
//                                                                              //
//  You should have received a copy of the GNU General Public License           //
//  along with buola.  If not, see <http://www.gnu.org/licenses/>.              //
//                                                                              //
//////////////////////////////////////////////////////////////////////////////////

#ifndef _BUOLA_ITERATOR_TRAITS_H_
#define _BUOLA_ITERATOR_TRAITS_H_

#include <buola/buola.h>

namespace buola {

///\addtogroup iterators
///@{

///\name Iterator traits
//@{
    
///caching random-access iterator tag

///Use this tag instead of std::random_access_iterator_tag if you want operator[] to return `value_type` instead of
///`reference`. operator[] works by creating a temporary iterator j, incrementing it and then returning *j. If *j
///returns a reference and the referred object is destroyed when the temporary iterator is destroyed,
///then an invalid reference will be returned. It is usually only necessary when the returned object
///is contained within the iterator (see \ref ICounter for an example).
struct GCachingRandomAccessIterator : public std::random_access_iterator_tag {};

///iterator category trait operator

///Obtain the category traversal tag for an iterator
template<typename tIterator>
using OIteratorCategory=typename std::iterator_traits<tIterator>::iterator_category;

///this trait query typedef can be used to know if an iterator supports a certain tag
template<typename tIterator,typename tTag>
using QIteratorSupports=std::is_base_of<tTag,OIteratorCategory<tIterator>>;

//@}

///@}

/*namespace buola*/ }

#endif
